// Version: 0.0.1

// Dependencies:
// JQuery.js
// UI.Core.js

// Supported Elements:
// <input type='checkbox'/>, <input type='radio'/>

$.widget('ui.checkBox',
{
	_init: function()
	{
		//  element
		var e = this.element.filter('input[type=checkbox],input[type=radio]');
	
		if (e.length == 0)
		{
			return false;
		}

		//  this         options           wrapper
		var self = this, o = this.options, w, clickElement;
		
		// We have to move it off the screen instead of hide it so the click event still fires.
		//e.addClass('.ui-helper-hidden-accessible');
		e.css({ left: '255px', position: 'absolute' });
		
		w = self.wrapper = e.wrap('<span class=\'ui-checkBox ui-state-default ui-icon\'></span>').parent();
		self.labels	     = e.parents('label');
		clickElement     = e;
		
		if (self.isRadio())
			w.addClass('ui-radio');
		
		if (self.labels.length == 0)
			clickElement = clickElement.add(w);
		
		if (e[0].id != '')
			self.labels  = self.labels.add($('label[for=' + e[0].id + ']'));

		o.value      = o.value || e[0].value;
		o.disabled   = o.disabled || e[0].disabled;
		o.threeState = (o.threeState || e.attr('threestate') || false) && !self.isRadio();
		o.checkState = (o.threeState && e.attr('indeterminate') || false) ? 
							$.ui.checkState.indeterminate : 
							(e[0].checked ? $.ui.checkState.checked : $.ui.checkState.unchecked);

		if (o.disabled)   w.addClass('ui-state-disabled');
		if (o.threeState) w.addClass('ui-checkBox-threeState');
		
		if (o.checkState == $.ui.checkState.checked)
			w.addClass(self.isRadio() ? 'ui-icon-bullet' : 'ui-icon-check');
		else if (o.checkState == $.ui.checkState.indeterminate)
		{
			e[0].checked = true;
			w.addClass('ui-icon-indeterminate');
		}
		else
			w.addClass('ui-icon-empty');

		clickElement.bind('click.checkBox', function()
		{
			var result = true;
			
			if (!o.disabled)
				if (self.isUnchecked() || self.isRadio())
					self.check();
				else
				{
					result = !(o.threeState && self.isChecked());
					self[(result) ? 'uncheck' : 'indeterminate']();
				}
			
			e.focus();
			
			return result;
		})
		.bind('focus.checkBox', function()
		{
			w.addClass('ui-state-focus');
		})
		.bind('blur.checkBox', function()
		{
			w.removeClass('ui-state-focus');
		})
		.add(self.labels).bind('mouseover.checkBox', function()
		{
			w.addClass('ui-state-hover');
		})
		.bind('mouseout.checkBox', function()
		{
			w.removeClass('ui-state-hover');
		});
	},
	destroy: function()
	{
		this.element
			.unbind('.checkBox')
			.removeData('checkBox')
			.removeClass('.ui-helper-hidden-accessible');
		
		this.labels.unbind('.checkBox');
		
		this.wrapper
			.unbind('.checkBox')
			.replaceWith(this.element);

		$.widget.prototype.destroy.apply(this, arguments); // default destroy

		return this;		
	},
	checkState: function(state)
	{
		if (state == undefined)
		{
			return this.options.checkState;
		}
	
		if (state != this.options.checkState &&
			(state >= $.ui.checkState.unchecked || $.ui.checkState <= $.ui.checkState.checked))
		{
			if (this.isRadio() && this.element[0].name.length > 0)
				$('span.ui-checkBox>input[type=radio][name=' + this.element[0].name + ']').not(this.element).checkBox('uncheck');

			this.options.checkState = state;
			this.element[0].checked = (!this.isUnchecked());

			this.wrapper
				[this.isUnchecked() ? 'addClass' : 'removeClass']('ui-icon-empty')
				[this.isChecked() ? 'addClass' : 'removeClass'](this.isRadio() ? 'ui-icon-bullet' : 'ui-icon-check')
				[this.isIndeterminate() ? 'addClass' : 'removeClass']('ui-icon-indeterminate');
		
			this._trigger('changed', null, {});
		}
	
		return this;
	},
	_setData: function(key, value)
	{
		switch (key)
		{
			case 'checkState':
				this.checkState(value);
			return;
			case 'disabled':
				this.element[0].disabled = value;
				this.options.disabled    = value;
				
				this.wrapper[value ? 'addClass' : 'removeClass']('ui-state-disabled');
			return;
			case 'value':
				this.element[0].value = value;
			break;
		}
		
		$.widget.prototype._setData.apply(this, arguments);
	},
	value: function(value)
	{
		if (value == undefined)
			return this.element[0].value;
		
		this._setData('value', value);
	},
	toggle: function()
	{
		this.element.trigger('click.checkBox');
	},
	check: function()
	{
		this.checkState($.ui.checkState.checked);
	},
	uncheck: function()
	{
		this.checkState($.ui.checkState.unchecked);
	},
	indeterminate: function()
	{
		this.checkState($.ui.checkState.indeterminate);
	},
	isChecked: function()
	{
		return (this.checkState() == $.ui.checkState.checked);
	},
	isUnchecked: function()
	{
		return (this.checkState() == $.ui.checkState.unchecked);
	},
	isIndeterminate: function()
	{
		return (this.checkState() == $.ui.checkState.indeterminate);
	},
	isRadio: function()
	{
		return (this.element[0].type == 'radio');
	}
});

$.ui.checkState =
	{
		unchecked: 0,
		checked: 1,
		indeterminate: 2
	};

$.extend(
	$.ui.checkBox,
	{
		defaults:
		{
			disabled: undefined,
			threeState: undefined,
			checkState: undefined,
			value: undefined,
			changed: false
		}
	}
);